
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.charset.Charset;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TextUtil{
	String x;
	static char[] CHARS="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~!@#$%^*()+-=&`[]{}\\|:;'\"/<>,.?".toCharArray();
	public static String  createRandomString( int len){
		char[] chs = new char[len];
		
		for(int i=0;i<len;i++){
			int pos =(int)(Math.random() * CHARS.length);
			chs[i] = CHARS[ pos ];
		}
		return new String(chs);
	}
	
	public static String MD5(String plaintext)  {
		return DigestUtils.md5Hex( plaintext );
	}

	@SuppressWarnings("rawtypes")
	public static String join(ArrayList arr, String seperater) {
		StringBuilder sb = new StringBuilder();
		int cnt = arr.size();
		for (int i = 0; i < cnt; i++) {
			if (i > 0)
				sb.append(seperater);
			sb.append(arr.get(i));
		}
		return sb.toString();
	} 
	public static String join(Object[] arr, String seperater) {
		StringBuilder sb = new StringBuilder();
		int cnt = arr.length;
		for (int i = 0; i < cnt; i++) {
			if (i > 0)
				sb.append(seperater);
			sb.append(arr[i]);
		}
		return sb.toString();
	}
	public static boolean isEmpty(String str){
		return str ==null || str.trim().isEmpty();
	}

	public static String replace( String str , Pattern pattern , Function<Matcher , String   > fun){
		Matcher matcher = pattern.matcher( str );
		String all = null ; 
		StringBuffer sb =new StringBuffer();
		while( matcher.find()){
			all = matcher.group(0); 
			String replace = (String)fun.apply(  matcher );			
			matcher.appendReplacement(sb, replace==null?"":replace );
		}
		matcher.appendTail(sb); 
		return sb.toString();  
	}
	public static String replace( String str , String pattern , Function<Matcher ,String  > fun){
		 Pattern p  = Pattern.compile( pattern);
		 return replace( str , p ,fun);
	}

	public static String replaceUnicode( String json ){
		if(json==null)
			return null;
		return replace( json ,  "\\\\u([a-fA-F\\d]{4})" ,  ( matcher -> {
			try{
				char ch = ( char ) Integer.parseInt( matcher.group( 1 ) ,16 );
				return ch + "" ;
			}catch( Exception ex  ){
				return matcher.group(0)	;
			}
		}));
	}
	public static String distinct( String retval , String separator ){
		if( retval == null )
			return "";
		String[] arr = retval.split( separator );
		Set<String> collection = new LinkedHashSet<>();
		for(String str : arr ){
			collection.add(  str  );
		}
		return StringUtils.join( collection , separator );
	}

	/**
	 * 从左边截取指定字节数的字符串 
	 * @param s
	 * @param length
	 * @return
	 */
	public  static  String leftBytesUCS2( String s, int  length)  {
		if( s==null )
			return null;
		Charset gbk = Charset.forName( "Unicode" );
		byte[] bytes = s.getBytes( gbk );
		if( bytes.length<= length )
			return s;
		int n = 0;  //  表示当前的字节数
		int i = 2;  //  要截取的字节数 ，从第3个字节开始
		for( ; i < bytes.length && n < length ; i++ ){
			//  奇数位置，如三、五、7等，为UCS2编码中两个字节的第二个字节
			if( i % 2 == 1 ){
				n++;  //  在UCS2第二个字节时n加1
			}else{
				//  当UCS2编码的第一个字节不等于0时，该UCS2字符为汉字，一个汉字算两个字节
				if( bytes[ i ] != 0 ){
					n++;
				}
			}
		}
		//  若是i为奇数时，处理成偶数
		if( i % 2 == 1 ){
			//  该UCS2字符是汉字时，去掉这个截一半的汉字
			if( bytes[ i - 1 ] != 0 )
				i = i - 1;
				//  该UCS2字符是字母或数字，则保留该字符
			else
				i = i + 1;
		}

		return new String( bytes , 0 , i   , gbk ); 
	}

	public static String Nvl( String txt1 , String text2 ){
		return (txt1 == null || txt1.isEmpty()) ?
			text2
			: txt1 ;
	}
	public static void trim( Object obj ){
		if( obj == null )
			return;
		if( obj instanceof String){
			return ;
		}
		Field[] fields = obj.getClass().getDeclaredFields();
		try{
			for( Field field : fields ){ 
				if( ( field.getModifiers() & (Modifier.FINAL |Modifier.STATIC|Modifier.ABSTRACT ) ) != 0    )
					continue;				
				field.setAccessible( true );
				Object value = field.get( obj );
				if( value instanceof String ){
					field.set( obj , StringUtils.trim( (String)value ) );
				}else if( value instanceof Collection ){
					for( Object o : ( Collection ) value ){
						if( !( o instanceof String ))
							trim( o );
					}

				}
			}
		}catch( IllegalAccessException ex ){
			throw new RuntimeException( ex );
		}

	}
	public static void main( String[] args ){
		System.out.println(  leftBytesUCS2( "参数错误：[请输入正确格式的日期时间: [yyyyMMdd];请传入[发票日期]]" , 50  ) );
	}

	public static String desensitizeId( String idCard ){
		if(StringUtils.isEmpty( idCard ))
			return idCard;
		if(idCard.length() ==11){
			return idCard.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
		}else if(idCard.length()==18) {
			return idCard.replaceAll("(?<=\\w{6})\\w(?=\\w{6})", "*");
		}
		return idCard;
	}
	/**
	 * 脱敏 
	 */
	public static String desensitize( String message ){
		if( message == null )
			return null;
		return message.replaceAll( "(^|[^\\w])(\\d{7})\\d{6}(\\d{4}[0-9X])([^\\w]|$)" , "$1$2******$3$4" )//身份证号
			.replaceAll( "(^|[^\\w])(1\\d{2})\\d{4}(\\d{4})([^\\w]|$)" , "$1$2******$3$4" );//手机号
	}

	public static boolean equalsEny( String source , String... codes){
		if(source==null || codes.length==0)
			return false;
		for( String code :codes){
			if( source.equals( code ))
				return true;
		}
		return false;
	}


	public static String sqlQuoteString( Object value ){
		if( value instanceof Boolean )
			return Boolean.TRUE.equals(  value ) ? "1" : "0";
		if( value instanceof Integer || value instanceof Float ||  value instanceof Double )
			return value.toString();
		String sValue = value.toString();
		return "'" + sValue.replace( "'" , "''" ) + "'";
	}

	public static String sqlQuoteList( Collection value ){
		List<String> list = Coll.map( value , p-> sqlQuoteString( p ) );
		return StringUtils.join( list , ","  );
	}
}
